export interface IVDebounceBinding {
  arg: keyof HTMLElementEventMap | undefined;
  modifiers: {
    wait: boolean;
    [key: number | string | symbol]: boolean;
  };
  value: (ev: Event) => any;
}

export const vDebounce = {
  type: "click" as keyof HTMLElementEventMap,
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el: HTMLElement, { modifiers, arg }: IVDebounceBinding) {
    // 默认为click事件
    if (!arg) {
      vDebounce.type = "click";
    } else {
      vDebounce.type = arg!;
    }

    const params = Object.keys(modifiers);

    if (params.length === 0) {
      el.delay = 1000;
      return;
    }

    const delayIndex = params.findIndex((item) => Number(item) >= 0);
    // 有参数，但是没有时间间隔毫秒数
    if (delayIndex < 0) {
      el.delay = 1000;
      return;
    }

    el.delay = parseInt(params[delayIndex]);
  },
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(
    el: HTMLElement,
    { modifiers, value: handleEvent }: IVDebounceBinding
  ) {
    el.addEventListener(
      vDebounce.type,
      async (event: Event) => {
        if (!modifiers.wait && !el.timer) {
          await handleEvent(event);

          el.timer = setTimeout(() => {
            el.timer && window.clearTimeout(el.timer);
            el.timer = null;
          }, el.delay);
          return;
        }

        el.timer && window.clearTimeout(el.timer);
        el.timer = setTimeout(async () => {
          await handleEvent(event);
          el.timer = null;
        }, el.delay);
      },
      false
    );
  },
  // 绑定元素的父组件卸载后调用
  unmounted(el: HTMLElement, { value }: IVDebounceBinding) {
    el.removeEventListener(vDebounce.type, value, false);
  },
};
